package com.travel.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.travel.constant.MessageConstant;
import com.travel.dto.AdminUserLoginDTO;
import com.travel.exception.BusinessException;
import com.travel.mapper.AdminUserMapper;
import com.travel.pojo.AdminUser;
import com.travel.service.AdminUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.Set;
import java.util.concurrent.TimeUnit;


/**
 * @author: libin
 * Date: 2025/6/12 17:48
 * Description:
 **/
@Slf4j
@Service
public class AdminUserServiceImpl extends ServiceImpl<AdminUserMapper, AdminUser> implements AdminUserService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final String LOGIN_PASSWORD_ERROR_KEY = "login:error:"; //密码错误标记的key
    private static final String LOGIN_LOCK_ERROR_KEY = "login:lock:"; //账号被锁定的key
    @Override
    public AdminUser login(AdminUserLoginDTO adminUserLoginDTO) {

        // 校验员工账号是否被锁定 .
        validateAccountLock(adminUserLoginDTO.getUsername());

        String username = adminUserLoginDTO.getUsername();
        LambdaQueryWrapper<AdminUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AdminUser::getUserName, username);
        AdminUser adminUser = this.getOne(wrapper);
        if (ObjectUtil.isEmpty(adminUser)){
            throw new BusinessException("用户不存在");
        }
        String password = DigestUtils.md5DigestAsHex(adminUserLoginDTO.getPassword().getBytes());
        if (!password.equals(adminUser.getPassword())) {
            log.info("密码比对错误");

            //1 记录员工密码错误的标记 , 并设置有效期为5分钟 .
            redisTemplate.opsForValue().set(getKey(username), "-", 5, TimeUnit.MINUTES);

            //2 获取该员工的密码错误标记 , 如果标记的数量 >= 5 , 设置账号锁定的标记
            Set<String> keys = redisTemplate.keys(LOGIN_PASSWORD_ERROR_KEY + username + ":*");

            if (keys != null && keys.size() >= 3) {
                log.info("员工登录密码3分钟之内, 错误次数超过三次, 锁定账号一小时");
                redisTemplate.opsForValue().set(LOGIN_LOCK_ERROR_KEY + username, "-", 1, TimeUnit.HOURS);
                throw new BusinessException(MessageConstant.LOGIN_LOCK_ERROR);
            }
            throw new BusinessException(MessageConstant.PASSWORD_ERROR);
        }
        return adminUser;
    }


    private void validateAccountLock(String username) {
        Object flag = redisTemplate.opsForValue().get(LOGIN_LOCK_ERROR_KEY + username);
        if (ObjectUtils.isNotEmpty(flag)) { //账号被锁定
            log.info("账号被锁定, 限制登录");
            throw new BusinessException(MessageConstant.LOGIN_LOCK_ERROR_MESSAGE);
        }
    }


    //拼接redis的key
    private String getKey(String username) {
        return LOGIN_PASSWORD_ERROR_KEY + username + ":" + RandomStringUtils.randomAlphabetic(5);
    }
}
